package cn.nr19.jian.`object`.function

import cn.nr19.jian.E2Factory
import cn.nr19.jian.J2Utils
import cn.nr19.jian.Jian
import cn.nr19.jian.factory.JsFactory
import cn.nr19.jian.`object`.ARR
import cn.nr19.jian.`object`.EON
import cn.nr19.jian.`object`.JianLei
import cn.nr19.jian.`object`.JianLeiApi
import cn.nr19.jian.`object`.JianObject
import java.io.UnsupportedEncodingException
import java.net.URLDecoder
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.text.SimpleDateFormat
import java.util.Date
import java.util.regex.Pattern

/**
 * 系统功能对象
 *  这里的lei  就相当于上下文
 */
open class JianSystemFunctionObject : JianObject {

    override fun pFun(data: JianLeiApi, name: String, pars: List<Any>): Any? {
        if (pars.size == 1){
            val par0 = pars[0]
            when(name){
                "到小数" ->  return Jian.toDouble(par0)
                "到文本" -> return Jian.Str(par0)
                "到整数" -> return Jian.toInt(par0)
                "到逻辑" -> return Jian.True(par0)
            }
        }

        return super.pFun(data, name, pars)
    }



    /**
     * App功能
     */
    open fun e2(lei : JianLeiApi, code : String, rule : String) : String{
        return E2Factory.text(code,rule,lei)
    }
    open fun e2s(lei : JianLeiApi, code : String, rule : String) : ARR {
        val ls = ARR()
        E2Factory.list(code,rule,lei)?.forEach {
            ls.add(it)
        }
        return ls
    }
    fun e2(lei: JianLeiApi, rule : String) : String{
        // 直接从源中获取
        return e2(lei,Jian.Str(lei.getVar("源")?:""),rule)
    }
    fun e2s(lei: JianLeiApi, rule : String) : ARR {
        // 直接从源中获取
        return e2s(lei,Jian.Str(lei.getVar("源")?:""),rule)
    }

    /***
     * 执行JS
     */
    open fun evalJS(lei: JianLeiApi,源 : String,脚本 : String):String{
        return JsFactory(源, JianLei(),"")
            .p(脚本)
    }

    /**
     * 数组
     */
    open fun 数组(): ARR = ARR()
    open fun 数据() : EON = EON()
    open fun 键对值(lei : JianLeiApi) : EON = EON()

    /**
     * @param ms 默认取到毫秒  13 位 Long， 否则返回 10位 Long
     */
    open fun 取当前时间戳(ms : Boolean) : Long{
        if (ms) return System.currentTimeMillis()
        else return (System.currentTimeMillis() / 1000).toLong()
    }

    /**
     * 默认10位时间戳
     */
    open fun 取当前时间戳(lei : JianLeiApi) : Long{

        return (System.currentTimeMillis() / 1000).toLong()
    }

    /**
     * 应写时间戳到文本
     */
    open fun 时间到文本(time : Long, pattern : String) : String{
        return 时间戳到文本(time, pattern)
    }
    open fun 时间到文本(i: Int, str : String) : String{
        return 时间戳到文本(i.toLong(),str)
    }

    /**
     * @param time 时间戳
     * @param pattern 返回日期类型 yyyy-MM-dd HH:mm:ss  年费-月份-日  时:分:秒   注意月份为大写MM
     */
    open fun 时间戳到文本(time : Long, pattern : String) : String{
        var milSecond = time
        if (milSecond.toString().length <= 10) {
            milSecond *= 1000
        }

        val date: Date = Date(milSecond)
        //pattern = "yyyy-MM-dd HH:mm:ss"
        val format = SimpleDateFormat(pattern)
        return format.format(date)
    }


    /**
     * 文本操作
     */
    open fun 到大写(str : String) : String = str.uppercase()
    open fun 到小写(str : String) : String = str.lowercase()
    open fun 删首空(str : String) : String = str.trimStart()
    open fun 删全部空(str : String):String = str.replace(" ","")
    open fun 删尾空(str : String) : String = str.trimEnd()
    open fun 删首尾空(str : String) : String = str.trim()

    //去除html的标识符号 返回文本
    open fun 取网页文本(源码: String) : String{
        return 源码.replace("<(/|)\\w+[^>]*>".toRegex(), "")
    }





    open fun 取文本长度(str : String) : Int{
        return str.length
    }


    // 指定长度 取左右  中间
    open fun 取文本(欲取其部分的文本 : String,开始位置 : Int, 结束位置 : Int) : String{
        return 欲取其部分的文本.substring(开始位置,结束位置)
    }
    open fun 取左边(str : String,lenght : Int):String =  Jian.def().取文本左边(str,lenght) ?: ""
    open fun 取右边(str : String,lenght : Int):String =  Jian.def().取文本右边(str,lenght) ?: ""
    open fun 取文本左边(欲取其部分的文本 : String, 欲取出字符的数目 : Int) : String{
        return 欲取其部分的文本.substring(0,欲取出字符的数目)
    }
    open fun 取文本右边(欲取其部分的文本 : String, 欲取出字符的数目 : Int) : String{
        return 欲取其部分的文本.substring(欲取其部分的文本.length - 欲取出字符的数目)
    }
    open fun 取文本左边(欲取其部分的文本 : String, 关键词 : String) : String {
        val ri: Int
        ri = 欲取其部分的文本.indexOf(关键词)
        return if (ri < 1) "" else 欲取其部分的文本.substring(0, ri)
    }
    open fun 取文本右边(欲取其部分的文本 : String, 关键词 : String) : String{
        val ri = 欲取其部分的文本.indexOf(关键词)
        return if (ri == -1) "" else 欲取其部分的文本.substring(ri + 关键词.length)
    }

    // 从右边开始寻找
    open fun 取文本左边2(欲取其部分的文本 : String, 关键词 : String) : String {
        val ri: Int
        ri = 欲取其部分的文本.lastIndexOf(关键词)
        return if (ri < 1) "" else 欲取其部分的文本.substring(0, ri)
    }
    open fun 取文本右边2(欲取其部分的文本 : String, 关键词 : String) : String{
        val ri = 欲取其部分的文本.lastIndexOf(关键词)
        return if (ri == -1) "" else 欲取其部分的文本.substring(ri + 关键词.length)
    }


    open fun 取文本左边3(欲取其部分的文本 : String, 关键词 : String,起始搜寻位置: Int) : String {
        val ri: Int
        ri = 欲取其部分的文本.indexOf(关键词,起始搜寻位置)
        return if (ri < 1) "" else 欲取其部分的文本.substring(0, ri)
    }
    open fun 取文本右边3(欲取其部分的文本 : String, 关键词 : String,起始搜寻位置: Int) : String{
        val ri = 欲取其部分的文本.indexOf(关键词,起始搜寻位置)
        return if (ri == -1) "" else 欲取其部分的文本.substring(ri + 关键词.length)
    }

    open fun 取文本中间(欲取其部分的文本 : String, 左边 : String, 右边 : String) : ARR {
        val ls = ARR()
        if (欲取其部分的文本.isEmpty() || 左边.isEmpty() || 右边.isEmpty()){
            return ls
        }
        var let = 欲取其部分的文本.indexOf(左边)
        while (let < 欲取其部分的文本.length){
            if (let == -1) return ls
            let += 左边.length
            val rit = 欲取其部分的文本.indexOf(右边, let)
            if (rit == -1) return ls
            ls.add(欲取其部分的文本.substring(let, rit))
            let = rit+1
        }
        return ls
    }
    open fun 取文本中间2(欲取其部分的文本 : String, 左边 : String, 右边 : String) : String{
        if (欲取其部分的文本.isEmpty() || 左边.isEmpty() || 右边.isEmpty())  return ""
        var let = 欲取其部分的文本.indexOf(左边)
        if (let == -1) return ""
        let += 左边.length
        val rit = 欲取其部分的文本.indexOf(右边, let)
        return if (rit == -1) "" else 欲取其部分的文本.substring(let, rit)
    }

    // indexOf
    open fun 寻找文本(被搜寻的文本 : String, 欲寻找的文本 : String) : Int{
        return 被搜寻的文本.indexOf(欲寻找的文本)
    }
    open fun 寻找文本(被搜寻的文本 : String, 欲寻找的文本 : String, 起始搜寻位置 : Int) : Int{
        return 被搜寻的文本.indexOf(欲寻找的文本,起始搜寻位置)
    }
    open fun 寻找文本(被搜寻的文本 : String,寻找文本 : String,起始位置 : Int,区分大小写 : Boolean) : Int = 被搜寻的文本.indexOf(寻找文本,起始位置,区分大小写)

    open fun 倒找文本(str : String, v : String) : Int{
        return str.lastIndexOf(v)
    }

    /**
     * 寻找下一个匹配文本位置，并排除转义字符
     * @param code 源代码
     * @param key 欲匹配的关键词
     * @param fromIndex 开始查询位置
     * @return 失败返回-1
     */
    open fun 寻找文本2(code: String, key: String?, fromIndex: Int): Int {
        var i = code.indexOf(key!!, fromIndex)
        while (i != -1) {
            // 排除转义
            if (是否为转义符(code, i)) {
                i = code.indexOf(key, i + 1)
                continue
            }
            // 取闭合
            return i
        }
        return -1
    }
    /**
     * 判断指定位置是否为转义值 是否转义 \
     * @return
     */
    open fun 是否为转义符(code: String, position: Int): Boolean {

        // 跳到上一个字符
        var i = position - 1
        if (i < 0) return false

        // 匹配前面所有 转义字符
        var zySize = 0 // 转义字符数量
        var word = code.substring(i, i + 1)
        while (word == "\\") {
            zySize++
            i--
            word = if (i >= 0) code.substring(i, i + 1) else ""
        }

        // 如果转义字符数量为单数，就是转义，否则前面的全是 \
        return zySize % 2 == 1
    }

    open fun 替换文本(str : String,l1 : String,l2 : String):String = str.replace(l1,l2)
    open fun 文本替换(str: String, old : String, to : String) : String{
        return str.replace(old,to)
    }
    open fun 文本替换2(str: String, start : Int, end : Int, to : String) : String{
        if (str.length < end)  return ""
        return str.substring(0,start) + to + str.substring(end)
    }
    open fun 文本替换3(str: String, old : String, to : String) : String{
        return str.replace(Regex(old),to).let {
            J2Utils.log("文本替换3")
            it
        }
    }
    open fun 翻转文本(str: String) : String{
        val ls = ArrayList<String>()
        str.forEach {
            ls.add(0,it.toString())
        }
        val p = StringBuilder()
        ls.forEach {
            p.append(it)
        }
        return p.toString()
    }
    open fun 比较(欲比较文本 : String,比较文本 : String,无视大小写 : Boolean) : Boolean{
        return 欲比较文本.equals(比较文本,无视大小写)
    }
    open fun 正则比较(欲比较文本 : String, 正则表达式 : String) : Boolean{
        if (欲比较文本 == 正则表达式) return true
        try {
            return if (欲比较文本.isEmpty() || 欲比较文本.isEmpty()) false
            else {
                val matcher = Pattern
                    .compile(正则表达式,Pattern.CASE_INSENSITIVE)
                    .matcher(欲比较文本)
                return matcher.find()
            }
        }catch (ex : java.lang.Exception){
            ex.printStackTrace()
            return false
        }
    }
    open fun 分割文本(str : String, split : String) : ARR {
        val arrs = ARR()
        str.split(split).forEach {
            arrs.add(it)
        }
        return arrs
    }

    // 正则匹配 匹配失败不会报错
    open fun 正则匹配(str : String, rule : String) : ARR {
        val o = ARR()
        try {
            val matcher = Pattern
                .compile(rule)
                .matcher(str)

            while(matcher.find()){
                val o2 = ARR()
                for (i in 0 until matcher.groupCount() + 1){
                    o2.add(matcher.group(i)?:"")
                }
                o.add(o2)
            }

        }catch (e : Exception){
            // App.log("正则匹配错误$e")
            e.printStackTrace()
        }

        return o
    }


    // ****************************************
    // ************ 加解密 *******************
    open fun md5(str : String) : String{
        var text = str
        val hash: ByteArray
        try {
            if (text.isEmpty()) text = "0" else if (text.length > 10240) text = text.substring(0, 10240)
            hash = MessageDigest.getInstance("MD5").digest(text.toByteArray(charset("UTF-8")))
        } catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
            return ""
        } catch (e: UnsupportedEncodingException) {
            e.printStackTrace()
            return ""
        }

        val hex = java.lang.StringBuilder(hash.size * 2)
        for (b in hash) {
            if (b.toInt() and 0xFF < 0x10) hex.append("0")
            hex.append(Integer.toHexString(b.toInt() and 0xFF))
        }

        return hex.toString()
    }
    open fun 取MD5值(str : String) : String{
        return md5(str)
    }

    open fun URL解码(源码 : String,编码 : String) : String{
        return if (源码.isEmpty()) "" else try {
            URLDecoder.decode(源码, 编码)
        } catch (e: UnsupportedEncodingException) {
            e.printStackTrace()
            源码
        }
    }

    /**
     * 正则读取
     * @param text
     * @param reg
     * @return 主分组[子表达式分组]
     */
    open fun 正则读取(text: String, reg: String): MutableList<MutableList<String>> {
        val lists: MutableList<MutableList<String>> = java.util.ArrayList()
        if (text.isEmpty() || reg.isEmpty()) return lists
        val matcher = Pattern
            .compile(reg, Pattern.MULTILINE)
            .matcher(text)
        while (matcher.find()) {
            val ls: MutableList<String> = java.util.ArrayList()

            // 第一个为匹配文本
            ls.add(matcher.group())

            // 1后面为子表达式列表
            for (i in 0 until matcher.groupCount()) {
                ls.add(matcher.group(i + 1) ?: return lists) // 子表达式从1开始
            }

            lists.add(ls)
        }
        return lists
    }

    // Android那边搞定咯 这里函数支持不了这么多



    // ****************************************
    // ************ 基础运算 *******************
    open fun 求反正切(i : Double) : Double = Math.atan(i)
    open fun 求反正弦(i : Double) : Double = Math.asin(i)
    open fun 求反余弦(i : Double) : Double = Math.acos(i)
    open fun 求余弦(i : Double) : Double = Math.cos(i)
    open fun 角度转弧度(i : Double) : Double = Math.toRadians(i)
    open fun 弧度转角度(i : Double) : Double = Math.toDegrees(i)
    open fun 取绝对值(i : Double) : Double = Math.abs(i)
    open fun 取绝对值(i : Int) : Int = Math.abs(i)
    open fun 取绝对值(i : Float) : Double = Math.abs(i).toDouble()
    open fun 取绝对值(i : Long) : Long = Math.abs(i)
    open fun 随机数(min: Int, max : Int) : Int {
        return (min + Math.random() * (max - min + 1)).toInt()
    }
    open fun 随机数(min: Long, max : Long) : Long {
        return (min + Math.random() * (max - min + 1)).toLong()
    }
    open fun 取随机数(min: Int, max : Int) : Int {
        return (min + Math.random() * (max - min + 1)).toInt()
    }
    open fun 取随机数(min: Long, max : Long) : Long {
        return (min + Math.random() * (max - min + 1)).toLong()
    }
    open fun 求自然对数(i : Double) : Double = Math.log(i)



    // ****************************************
    // ************ 基本类型操作 *******************

    open fun 长度(str : String):Int = str.length
    open fun 长度(str : Int):Int = str.toString().length


}